package fun._6742.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import fun._6742.interceptor.LoginInterceptor;
import fun._6742.mapper.CartItemMapper;
import fun._6742.mapper.CartMapper;
import fun._6742.model.dataobject.CartDO;
import fun._6742.model.dataobject.CartItemDO;
import fun._6742.model.valueobject.CartItemVO;
import fun._6742.model.valueobject.CartVO;
import fun._6742.model.valueobject.LoginUser;
import fun._6742.model.valueobject.ProductVO;
import fun._6742.request.CartItemRequest;
import fun._6742.request.GoodsStatusRequest;
import fun._6742.service.CartService;
import fun._6742.service.ProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CartServiceImpl implements CartService {

    @Resource
    ProductService productService;

    @Resource
    CartMapper cartMapper;

    @Resource
    CartItemMapper cartItemMapper;

    @Override
    public void addItemToCartOrUpdate(CartItemRequest cartItemRequest) {
        LoginUser loginUser = LoginInterceptor.threadLocal.get();
        long productId = cartItemRequest.getId();
        // 查找判断商品是否存在
        productService.findDetail(productId);

        int buyNum = cartItemRequest.getNum();
        // 获取购物车
        CartDO cartDO = cartMapper.selectOne(new QueryWrapper<CartDO>().eq("user_id", loginUser.getId()));
        if (null == cartDO) {
            cartDO = CartDO.builder().userId(loginUser.getId()).build();
            cartMapper.insert(cartDO);
        }
        List<CartItemDO> cartItemDOList =
                cartItemMapper.selectList(new QueryWrapper<CartItemDO>().eq("cart_id", cartDO.getId()));
        // 判断购物车中是否有该商品
        if (productInCart(cartItemDOList, productId)) {
            // 如果有，修改数量
            CartItemDO cartItemDO = cartItemDOList.stream()
                    .filter(obj -> obj.getProductId().equals(productId)).findFirst().get();
            cartItemDO.setProductNum(buyNum);
            cartItemMapper.updateById(cartItemDO);
        } else {
            // 如果没有，新增
            CartItemDO cartItemDO = CartItemDO.builder()
                    .cartId(cartDO.getId())
                    .productId(productId)
                    .productNum(buyNum).build();
            cartItemMapper.insert(cartItemDO);
        }
    }

    private Boolean productInCart(List<CartItemDO> cartItemDOList, long productId) {
        return cartItemDOList.stream().anyMatch(obj -> obj.getProductId().equals(productId));
    }

    @Override
    public void delAllCartItems() {
        LoginUser loginUser = LoginInterceptor.threadLocal.get();
        CartDO cartDO = cartMapper.selectOne(new QueryWrapper<CartDO>().eq("user_id", loginUser.getId()));
        if (null == cartDO) {
            cartDO = CartDO.builder().userId(loginUser.getId()).build();
            cartMapper.insert(cartDO);
        }
        cartItemMapper.delete(new QueryWrapper<CartItemDO>().eq("cart_id", cartDO.getId()));
    }

    @Override
    public CartVO viewCart() {
        LoginUser loginUser = LoginInterceptor.threadLocal.get();
        CartDO cartDO = cartMapper.selectOne(new QueryWrapper<CartDO>().eq("user_id", loginUser.getId()));
        if (null == cartDO) {
            cartDO = CartDO.builder().userId(loginUser.getId()).build();
            cartMapper.insert(cartDO);
            return new CartVO();
        }
        List<CartItemDO> cartItemDOList =
                cartItemMapper.selectList(new QueryWrapper<CartItemDO>().eq("cart_id", cartDO.getId()));
        if (cartItemDOList.isEmpty()) {
            return new CartVO();
        }
        Map<Long, ProductVO> productMap = productService.findProductsBatchById(cartItemDOList.stream()
                .map(CartItemDO::getProductId).collect(Collectors.toList()));
        List<CartItemVO> cartItemVOList = cartItemDOList.stream().map(
                        obj -> {
                            if (null == productMap.get(obj.getProductId())) {
                                deleteItemBatchByProductId(obj.getProductId());
                                return null;
                            } else {
                                return new CartItemVO(obj, productMap.get(obj.getProductId()));
                            }
                        }
                )
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        CartVO cartVO = new CartVO(cartItemVOList);
        // 更新购物车数据
        cartDO.update(cartVO);
        cartMapper.updateById(cartDO);
        return cartVO;
    }

    @Override
    public void deleteItemBatchByProductId(Long productId) {
        List<Long> idList = cartItemMapper.selectList(new QueryWrapper<CartItemDO>().eq("product_id", productId))
                .stream().map(CartItemDO::getId).collect(Collectors.toList());
        if (idList.size() == 0) {
            return;
        }
        cartItemMapper.deleteBatchIds(idList);
        log.info("deleteProduct:res:true,id:{}", idList);
    }

    @Override
    public void delBatchCartItems(List<Long> productIds) {
        LoginUser loginUser = LoginInterceptor.threadLocal.get();
        CartDO cartDO = cartMapper.selectOne(new QueryWrapper<CartDO>().eq("user_id", loginUser.getId()));
        if (null == cartDO) {
            cartDO = CartDO.builder().userId(loginUser.getId()).build();
            cartMapper.insert(cartDO);
        }
        cartItemMapper.delete(new QueryWrapper<CartItemDO>().eq("cart_id", cartDO.getId()).in("product_id", productIds));
    }

    @Override
    public void updateCartItems(GoodsStatusRequest goodsStatusRequest) {
        LoginUser loginUser = LoginInterceptor.threadLocal.get();
        CartDO cartDO = cartMapper.selectOne(new QueryWrapper<CartDO>().eq("user_id", loginUser.getId()));
        CartItemDO cartItemDO = cartItemMapper.selectOne(
                new QueryWrapper<CartItemDO>().eq("cart_id", cartDO.getId()).eq("product_id", goodsStatusRequest.getProductId()));
        cartItemDO.setGoodsStatus(goodsStatusRequest.getGoods_status());
        cartItemMapper.updateById(cartItemDO);
    }
}
